<?php
namespace Apps\Frontend\Models;
use Phalcon\Mvc\Model;
class Category extends Model{
    public $id;
    public $name;
    public $alias;
    public $keyword=0;
    public $description=0;
    public $link;
    public $price;
    public $sell=0;
    public $content_sell=0;
    public $comment=0;
    public $modified_by=0;
    public $created=0;
    public $product_id =0;
    public $created_by =0;
    public $modified =0;
    public $status=1;
    public $check_out=1;
    public $check_timeout=0;
    //set value
    protected $_data;
    protected $_parent_id;
    protected $_id;
    public 	$_orderArr;
    protected $table = 'ph_vegalife_category';

    public function initialize(){//ham khoi tao chỉ gọi 1 lần trong thời gian yêu cầu
        $this->setSource("ph_vegalife_category");
        
        $this->belongsTo('created_by', 'Apps\Frontend\Models\Users', 'id', array(
            'alias' => 'create',
            'reusable' => true
        ));
        $this->belongsTo('check_out', 'Apps\Frontend\Models\Users', 'id', array(
            'alias' => 'check',
            'reusable' => true
        ));
    }

    //lay thong tin node can thiet
    protected function getNodeInfo($id) {
        return $this::findFirst($id);
    }
    //Xóa bỏ node
    public function removeNode($id,$options = 'branch'){
        $this->_id = $id;
        if($options == 'branch' || $options == null ) $this->removeBranch();

        if($options == 'one') $this->removeOne($id);
    }
    protected function removeBranch(){
        $infoNodeRemove  = $this->getNodeInfo($this->_id);
        $left = $infoNodeRemove->lft;
        $right = $infoNodeRemove->rgt;
        $widthNodeRemove = $this->widthNode($left, $right);
        $sql = "DELETE FROM " . $this->table . ' WHERE lft BETWEEN ' . $left . ' AND ' . $right;
        $this->getReadConnection()->query($sql);

        $sqlUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = (lft - ' . $widthNodeRemove . ') WHERE lft > ' .$right;
        $this->getReadConnection()->query($sqlUpdateLeft);
        $sqlUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = (rgt - ' . $widthNodeRemove . ') WHERE rgt > ' .$right;
        $this->getReadConnection()->query($sqlUpdateRight);
    }
    //xóa hẳn 1 node
    protected function removeOne($id) {
        $nodeInfo = $this->getNodeInfo($id);
        $resultSet = $this::find(array('parent = ' . $id, 'order' => 'lft DESC'));
        foreach ($resultSet as $k => $v) {
            $childIds[] = $v->id;
        }
        rsort($childIds);
        if (count($childIds) > 0) {
            foreach ($childIds as $key => $val) {
                $data = array();
                $data['id'] = $val;
                $data['parent'] = $nodeInfo->parent;
                $this->moveNode($data, array('option' => 'after', 'brother_id' => $nodeInfo->id));
            }
            $this->removeNode($nodeInfo->id);
        }
    }
    public  function  updateNode($data, $id = null, $newParentID = 0){
        if($id != 0 && $id > 0 && count($data)!=0  ){
            $infoNode = $this->getNodeInfo($id);
            $strUpdate = $this->createUpdateQuery($data);
            $sql = 'UPDATE ' . $this->table . ' SET ' . $strUpdate . ' WHERE id =  ' . $id;
            $this->getReadConnection()->query($sql);
            if($newParentID > 0 && $newParentID != null){
                if($infoNode->parent != $newParentID){
                    $this->moveNode($id, $newParentID);
                }
            }
        }else {
            $strUpdate = $this->createUpdateQuery($data);
            $sql = 'UPDATE ' . $this->table . ' SET ' . $strUpdate . ' WHERE id  ' . $id;
            $this->getReadConnection()->query($sql);
        }
    }
    public function insertNode($data,$parent = 1,$options = null){
        $this->_data = $data;
        $this->_parent_id = $parent;
        if($options['position'] == 'right' || $options == null ) $newId = $this->insertRight();
        if($options['position'] == 'left') $newId = $this->insertLeft();
        if($options['position'] == 'before') $newId = $this->insertBefore($options['brother_id']);
        if($options['position'] == 'after') $newId = $this->insertAfter($options['brother_id']);
        return $newId;
    }
    //insert vi trí bên phải
    public function insertRight(){
        $parentInfo  = $this->getNodeInfo($this->_parent_id);
        $parentRight = $parentInfo->rgt;
        $sqlUpdateLeft = 'UPDATE ' .$this->table . ' SET lft = (lft + 2) ' . ' WHERE lft > ' . $parentRight;
        $this->getReadConnection()->query($sqlUpdateLeft);
        $sqlUpdateRight = 'UPDATE ' .$this->table . ' SET rgt = (rgt + 2) ' . ' WHERE rgt >= ' . $parentRight;
        $this->getReadConnection()->query($sqlUpdateRight);
        $data = $this->_data;
        $data['parent'] 	= $parentInfo->id; //$this->_parent_id
        $data['lft'] 		= $parentRight;
        $data['rgt'] 		= $parentRight + 1;
        $data['level'] 		= $parentInfo->level + 1;
        $newQuey = $this->createInsertQuery($data);
        $sqlInsert = 'INSERT INTO ' . $this->table . " (" . $newQuey['cols'] . ") " . " VALUES(" . $newQuey['vals'] . ")";
        $this->getReadConnection()->query($sqlInsert);
        /*  $category = new Category();
          $newId = $category->getConnection()->lastInsertId();*/
        return $this->_id;
    }
    //insert vi trí bên trái
    public function insertLeft(){
        $parentInfo  = $this->getNodeInfo($this->_parent_id);
        $parentLeft = $parentInfo->lft;
        $sqlUpdateLeft = 'UPDATE ' .$this->table . ' SET lft = (lft + 2) ' . ' WHERE lft >= ' . ($parentLeft + 1);
        $this->getReadConnection()->query($sqlUpdateLeft);
        $sqlUpdateRight = 'UPDATE ' .$this->table . ' SET rgt = (rgt + 2) ' . ' WHERE rgt > ' . ($parentLeft + 1);
        $this->getReadConnection()->query($sqlUpdateRight);
        $data = $this->_data;
        $data['parent'] 	= $parentInfo->id; //$this->_parent_id
        $data['lft'] 		= $parentLeft + 1;
        $data['rgt'] 		= $parentLeft + 2;
        $data['level'] 		= $parentInfo->level + 1;
        $newQuey = $this->createInsertQuery($data);
        $sqlInsert = 'INSERT INTO ' . $this->table . "  (" . $newQuey['cols'] . ") " . " VALUES(" . $newQuey['vals'] . ")";
        $this->getReadConnection()->query($sqlInsert);
        return $this->_id;
    }
    //insert vi trí bên trước node
    public function insertBefore($brother_id){
        $parentInfo  = $this->getNodeInfo($this->_parent_id);
        $brothderInfo = $this->getNodeInfo($brother_id);
        $sqlUpdateLeft = 'UPDATE ' .$this->table . ' SET lft = (lft + 2) ' . ' WHERE lft >= ' . $brothderInfo->lft;
        $this->getReadConnection()->query($sqlUpdateLeft);
        $sqlUpdateRight = 'UPDATE ' .$this->table . ' SET rgt = (rgt + 2) ' . ' WHERE rgt >= ' . ( $brothderInfo->lft + 1);
        $this->getReadConnection()->query($sqlUpdateRight);
        $data = $this->_data;
        $data['parent'] 	= $parentInfo->id; //$this->_parent_id
        $data['lft'] 		= $brothderInfo->lft;
        $data['rgt'] 		= $brothderInfo->lft +1;
        $data['level'] 		= $parentInfo->level + 1;
        $newQuey = $this->createInsertQuery($data);
        $sqlInsert = 'INSERT INTO ' . $this->table . " (" . $newQuey['cols'] . ") " . " VALUES(" . $newQuey['vals'] . ")";
        $this->getReadConnection()->query($sqlInsert);
        return $this->_id;
    }
    //insert vào vị trí phía sau node
    protected function insertAfter($brother_id){
        $parentInfo  = $this->getNodeInfo($this->_parent_id);
        $brothderInfo = $this->getNodeInfo($brother_id);
        $sqlUpdateLeft = 'UPDATE ' .$this->table . ' SET lft = (lft + 2) ' . ' WHERE lft > ' . $brothderInfo->rgt;
        $this->getReadConnection()->query($sqlUpdateLeft);
        $sqlUpdateRight = 'UPDATE ' .$this->table . ' SET rgt = (rgt + 2) ' . ' WHERE rgt > ' . $brothderInfo->rgt;
        $this->getReadConnection()->query($sqlUpdateRight);
        $data = $this->_data;
        $data['parent'] 	= $parentInfo->id; //$this->_parent_id
        $data['lft'] 		= $brothderInfo->rgt + 1;
        $data['rgt'] 		= $brothderInfo->rgt + 2;
        $data['level'] 		= $parentInfo->level + 1;
        $newQuey = $this->createInsertQuery($data);
        $sqlInsert = 'INSERT INTO ' . $this->table . " (" . $newQuey['cols'] . ") " . " VALUES(" . $newQuey['vals'] . ")";
        $this->getReadConnection()->query($sqlInsert);
        return $this->_id;
    }
    //dich chuyển node
    public function moveNode($id, $parent, $options = null){
        $this->_id = $id;
        $this->_parent_id = $parent;
        if($options['position'] == 'right' || $options == null ) $this->moveRight();
        if($options['position'] == 'left') $this->moveLeft();
        if($options['position'] == 'before') $this->moveBefore($options['brother_id']);
        if($options['position'] == 'after') $this->moveAfter($options['brother_id']);
    }
    //dich chuyển node qua phải
    protected function moveRight(){
        $infoMoveNode = $this->getNodeInfo($this->_id);
        $lftMoveNode = $infoMoveNode->lft; // 3
        $rgtMoveNode = $infoMoveNode->rgt; // 6
        $widthMoveNode = $this->widthNode($lftMoveNode, $rgtMoveNode);
        $sqlReset = 'UPDATE ' . $this->table . ' SET lft = (lft - ' . $lftMoveNode . '),rgt = (rgt - ' . $rgtMoveNode . ') WHERE lft BETWEEN ' . $lftMoveNode . ' AND ' . $rgtMoveNode;
        $this->getReadConnection()->query($sqlReset);

        $sqlUpdateRight = 'UPDATE ' . $this->table . ' SET rgt = (rgt - ' . $widthMoveNode . ') WHERE rgt > ' . $rgtMoveNode;
        $this->getReadConnection()->query($sqlUpdateRight);

        $sqlUpdateLeft = 'UPDATE ' . $this->table . ' SET lft = (lft - ' . $widthMoveNode . ') WHERE lft > ' . $rgtMoveNode;
        $this->getReadConnection()->query($sqlUpdateLeft);

        $infoParentNode = $this->getNodeInfo($this->_parent_id);
        $rgtParentNode = $infoParentNode->rgt;
        $sqlUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = (lft + ' . $widthMoveNode . ') WHERE lft >= ' . $rgtParentNode . ' AND rgt > 0';
        $this->getReadConnection()->query($sqlUpdateLeft);

        $sqlUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = (rgt + ' . $widthMoveNode . ') WHERE rgt >= ' . $rgtParentNode;
        $this->getReadConnection()->query($sqlUpdateRight);

        $levelMoveNode = $infoMoveNode->level;
        $levelParentNode = $infoParentNode->level;
        $sqlUpdateLevel = 'UPDATE ' . $this->table . ' SET level = (level - ' . $levelMoveNode . '+' . $levelParentNode . '+ 1) WHERE rgt <=0';
        $this->getReadConnection()->query($sqlUpdateLevel);

        $sqlUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = (lft + ' . $infoParentNode->rgt . ') WHERE rgt <= 0 ';
        $this->getReadConnection()->query($sqlUpdateLeft);

        $sqlUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = (rgt + ' . $infoParentNode->rgt . '+' . $widthMoveNode . '- 1) WHERE rgt <= 0 ';
        $this->getReadConnection()->query($sqlUpdateRight);

        $sqlUpdateNode = ' UPDATE ' . $this->table . ' SET parent = ' .  $infoParentNode->id . ' WHERE id = ' . $infoMoveNode->id;
        $this->getReadConnection()->query($sqlUpdateNode);
    }
    //dich chuyen node qua trái
    public function moveLeft(){
        $infoMoveNode = $this->getNodeInfo($this->_id);
        $lftMoveNode = $infoMoveNode->lft; // 3
        $rgtMoveNode = $infoMoveNode->rgt; // 6
        $widthMoveNode = $this->widthNode($lftMoveNode, $rgtMoveNode);
        $sqlReset = 'UPDATE ' . $this->table . ' SET lft = (lft - ' . $lftMoveNode . '),rgt = (rgt - ' . $rgtMoveNode . ') WHERE lft BETWEEN ' . $lftMoveNode . ' AND ' . $rgtMoveNode;
        $this->getReadConnection()->query($sqlReset);
        $sqlUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = (lft - ' . $widthMoveNode . ' ) WHERE lft > ' . $rgtMoveNode;
        $this->getReadConnection()->query($sqlUpdateLeft);
        $sqlUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = (rgt - ' . $widthMoveNode . ') WHERE rgt > ' . $rgtMoveNode;
        $this->getReadConnection()->query($sqlUpdateRight);
        $infoParentNode = $this->getNodeInfo($this->_parent_id);
        $lftParentNode = $infoParentNode->lft;
        $sqlUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = (lft + ' . $widthMoveNode . ') WHERE lft > ' . $lftParentNode .' AND rgt >0';
        $this->getReadConnection()->query($sqlUpdateLeft);
        $sqlUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = (rgt + ' . $widthMoveNode . ') WHERE rgt > ' . $lftParentNode;
        $this->getReadConnection()->query($sqlUpdateRight);
        $levelMoveNode = $infoMoveNode->level;
        $levelParentNode = $infoParentNode->level;
        $sqlUpdateLevel = 'UPDATE ' . $this->table . ' SET level = (level - ' . $levelMoveNode . '+' . $levelParentNode . '+ 1) WHERE rgt <=0';
        $this->getReadConnection()->query($sqlUpdateLevel);
        $sqlUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = (lft + ' . $infoParentNode->lft . '+' . ' 1) WHERE rgt <= 0 ';
        $this->getReadConnection()->query($sqlUpdateLeft);
        $sqlUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = (rgt + ' . $infoParentNode->lft . '+' . $widthMoveNode . ') WHERE rgt <= 0 ';
        $this->getReadConnection()->query($sqlUpdateRight);
        $sqlUpdateNode = ' UPDATE ' . $this->table . ' SET parent = ' .  $infoParentNode->id . ' WHERE id = ' . $infoMoveNode->id;
        $this->getReadConnection()->query($sqlUpdateNode);
    }
    //dihc chuyen truoc node
    protected function moveBefore($brother_id){
        $infoMoveNode = $this->getNodeInfo($this->_id);
        $lftMoveNode = $infoMoveNode->lft; // 3
        $rgtMoveNode = $infoMoveNode->rgt; // 6
        $widthMoveNode = $this->widthNode($lftMoveNode, $rgtMoveNode);

        //$sqlReset
        $sqlReset = 'UPDATE ' . $this->table . ' SET rgt = (rgt - ' . $rgtMoveNode . '), lft = (lft - ' . $lftMoveNode . ') WHERE lft BETWEEN ' . $lftMoveNode . ' AND ' . $rgtMoveNode;
        $this->getReadConnection()->query($sqlReset);
        //$slqUpdateRight
        $slqUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = ( rgt - ' . $widthMoveNode . ') WHERE rgt > ' . $rgtMoveNode;
        $this->getReadConnection()->query($slqUpdateRight);
        //$slqUpdateLeft
        $slqUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = ( lft - ' . $widthMoveNode . ') WHERE lft > ' . $rgtMoveNode;
        $this->getReadConnection()->query($slqUpdateLeft);

        $infoBrotherNode = $this->getNodeInfo($brother_id);
        $lftBrotherNode = $infoBrotherNode->lft;
        //$slqUpdateLeft
        $slqUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = ( lft + ' . $widthMoveNode . ') WHERE lft >= ' . $lftBrotherNode . ' AND rgt > 0';
        $this->getReadConnection()->query($slqUpdateLeft);
        //$slqUpdateRight
        $slqUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = ( rgt + ' . $widthMoveNode . ') WHERE rgt >= ' . $lftBrotherNode;
        $this->getReadConnection()->query($slqUpdateRight);

        $infoParentNode 	= $this->getNodeInfo($this->_parent_id);
        $levelMoveNode 		= $infoMoveNode->level;
        $levelParentNode	= $infoParentNode->level;
        $newLevelMoveNode   = $levelParentNode + 1;
        //$slqUpdateLevel
        $slqUpdateLevel = 'UPDATE ' . $this->table . ' SET level = ( level - ' . $levelMoveNode . '+' . $newLevelMoveNode . ') WHERE rgt <=0';
        $this->getReadConnection()->query($slqUpdateLevel);
        //
        $newParent 	= $infoParentNode->id;
        $newLeft 	= $infoBrotherNode->lft;
        $newRight 	= $infoBrotherNode->lft + $widthMoveNode - 1;
        //
        $slqUpdateParent = 'UPDATE ' . $this->table . '
						  SET parent = ' . $newParent . ',
						      lft = ' . $newLeft . ',
						  	  rgt = ' . $newRight . '
						  WHERE id = ' . $this->_id;
        $this->getReadConnection()->query($slqUpdateParent);
        //$slqUpdateNode
        $slqUpdateNode = 'UPDATE ' . $this->table . '
						  SET rgt = (rgt +  ' . $newRight . '),
						   	  lft = (lft +  ' . $newLeft . ')
						  WHERE rgt <0';
        $this->getReadConnection()->query($slqUpdateNode);
    }
    protected function moveAfter($brother_id){
        $infoMoveNode = $this->getNodeInfo($this->_id);
        $lftMoveNode = $infoMoveNode->lft; // 3
        $rgtMoveNode = $infoMoveNode->rgt; // 6
        $widthMoveNode = $this->widthNode($lftMoveNode, $rgtMoveNode);
        //reset node
        $sqlReset = 'UPDATE ' . $this->table . ' SET rgt = ( rgt - ' . $rgtMoveNode . '), lft = (lft - ' . $lftMoveNode . ') WHERE lft BETWEEN ' . $lftMoveNode . ' AND ' . $rgtMoveNode;
        $this->getReadConnection()->query($sqlReset);
        //update right
        $slqUpdateRight = ' UPDATE ' . $this->table . ' SET rgt = ( rgt - ' . $widthMoveNode . ') WHERE rgt  > ' . $rgtMoveNode;
        $this->getReadConnection()->query($slqUpdateRight);
        // //update left
        $slqUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = (lft - ' . $widthMoveNode . ') WHERE lft > ' . $rgtMoveNode;
        $this->getReadConnection()->query($slqUpdateLeft);

        $infoBrotherNode = $this->getNodeInfo($brother_id);
        $rgtBrotherNode = $infoBrotherNode->rgt;
        //UpdateLeft
        $slqUpdateLeft = ' UPDATE ' . $this->table . ' SET lft = ( lft + ' . $widthMoveNode . ') WHERE lft > ' . $rgtBrotherNode .' AND rgt>0';
        $this->getReadConnection()->query($slqUpdateLeft);
        //$sqlUpdateRight
        $sqlUpdateRight = ' UPDATE ' . $this->table . '  SET rgt = ( rgt + ' . $widthMoveNode . ') WHERE rgt > ' . $rgtBrotherNode;
        $this->getReadConnection()->query($sqlUpdateRight);

        $infoParentNode = $this->getNodeInfo($this->_parent_id);
        $levelMoveNode = $infoMoveNode->level;
        $levelParentNode = $infoParentNode->level;
        $newLevelMoveNode  = $levelParentNode + 1;
        //$sqlUpdateLevel
        $sqlUpdateLevel = 'UPDATE ' . $this->table . ' SET level = ( level - ' . $levelMoveNode . '+' . $newLevelMoveNode . ') WHERE rgt <=0';
        $this->getReadConnection()->query($sqlUpdateLevel);
        //
        $newParent 	= $infoParentNode->id;
        $newLeft 	= $infoBrotherNode->rgt + 1;
        $newRight 	= $infoBrotherNode->rgt + $widthMoveNode;
        //$sqlUpdateNode
        $slqUpdateParent = ' UPDATE ' . $this->table . ' SET parent = ' .  $newParent . ', lft = ' . $newLeft . ',
                           rgt = ' . $newRight . ' WHERE id = ' . $this->_id;
        $this->getReadConnection()->query($slqUpdateParent);
        //$slqUpdateNode
        $slqUpdateNode = 'UPDATE ' . $this->table . '
						  SET rgt = (rgt +  ' . $newRight . '),
						   	  lft = (lft +  ' . $newLeft . ')
						  WHERE rgt <0';
        $this->getReadConnection()->query($slqUpdateNode);
    }

    public function widthNode($lftMoveNode,$rgtMoveNode){
        $widthMoveNode = $rgtMoveNode - $lftMoveNode + 1;
        return $widthMoveNode;
    }
    //dich chuyen xuong node
    public function moveDown($id) {
        $nodeInfo = $this->getNodeInfo($id);
        $parentInfo = $this->getNodeInfo($nodeInfo->parent);
        $resultSet = $this::findFirst(array('lft > ' . $nodeInfo->lft . ' AND parent = ' . $nodeInfo->parent,'columns'=>'id','order'=>'lft ASC'));
        $this->moveNode($id,$parentInfo->id, array('position' => 'after', 'brother_id' => $resultSet->id));

    }
    //dich chuyen len tren node
    public function moveUp($id) {
        $nodeInfo = $this->getNodeInfo($id);
        $parentInfo = $this->getNodeInfo($nodeInfo->parent);
        $resultSet = $this::findFirst(array('lft < ' . $nodeInfo->lft . ' AND parent = ' . $nodeInfo->parent,'columns'=>'id','order'=>'lft DESC'));
        $this->moveNode($id,$parentInfo->id, array('position' => 'before', 'brother_id' => $resultSet->id));

    }
    //tạo câu truy vấn update
    protected function createUpdateQuery($data){
        if(count($data)>0){
            $result = '';
            $i = 1;
            foreach ($data as $key => $val){
                if($i == 1){
                    $result .= " " . $key . "= '" . $val . "'";
                }else{
                    $result .= ", " . $key . "= '" . $val . "'";
                }
                $i++;
            }
            return $result;
        }
    }
    //tao cau insert vào database
    protected function createInsertQuery($data = null){
        if(count($data)>0 ){
            $cols = '';
            $vals = '';
            $i = 1;
            foreach ($data as $key => $value){
                if($i == 1){
                    $cols .= "`" . $key . "`";
                    $vals .= "'" . $value . "'";
                }else{
                    $cols .= ",`" . $key . "`";
                    $vals .= ",'" . $value . "'";
                }
                $i++;
            }
            $newQuery['cols'] =  $cols;
            $newQuery['vals'] =  $vals;
        }
        return $newQuery;
    }
    //Cập nhật thêm 1 số function
    /*
     * Get info of parent node
     * @param  int ID of node which you want get info
     */
    public function getParentNode($id){
        $infoNode = $this->getNodeInfo($id);
        $parentId = $infoNode->parents;
        $infoParentNode = $this->getNodeInfo($parentId);
        return $infoParentNode;
    }
    /*
     *  Update ordering of all node in tree
     * @param  array An array store info tree
	 * @param  array An array store info of ordering
	 * @return Change tree structure.
     */
    public function orderTree($data,$orderArr){

        $orderGroup = $this->orderGroup($data);
        //$newOrderGroup = array();
        foreach ($orderGroup as $key => $val){
            $tmpVal = array();
            foreach ($val as $key2 => $val2){
                $tmpVal[$key2] = $orderArr[$key2];
            }
            natsort($tmpVal);
            $orderGroup[$key] = $tmpVal;
        }

        foreach ($orderGroup as $key => $val){
            $tmpVal = array();
            foreach ($val as $key2 => $val2){
                $info = $this->getNodeByLeft($key2);
                $tmpVal[$info['id']] = $val2;
            }
            $orderGroup[$key] = $tmpVal;
        }

        foreach ($orderGroup as $key => $val){
            foreach ($val as $key2 => $val2){
                $nodeID = $key2;
                $parent = $key;
                $this->moveNode($nodeID, $parent);
            }
        }
    }
    /**
     * Get info of node
     * @param  int Left value of node
     * @return array Node info.
     */
    protected function getNodeByLeft($left){
        return $this::find(array("lft = $left"));
    }
    /**
     * Create node groups
     * @param  array An array store info tree
     * @return array of node groups
     */
    public function orderGroup($data = null){
        if($data != null){
            $orderArr = array();
            if(count($data)>0){
                foreach ($data as $key => $val){
                    $orderArr[$val['id']] = array();
                    if(isset($orderArr[$val['parents']])){
                        $orderArr[$val['parents']][] = $val['lft'];
                    }
                }
                $orderArr2 = array();
                foreach ($orderArr as $key => $val){
                    $tmp = array();
                    $tmp = $orderArr[$key];
                    if(count($tmp)>0){
                        $orderArr2[$key] = array_flip($val);
                    }
                }

            }
        }
        $this->_orderArr = $orderArr2;
        return $this->_orderArr;
    }
    /**
     * Create ordering of node by left value
     * @param int ID of parent of current node
     * @param int Letf value of current node
     *
     * @return int An value of ordering
     *
     */
    public function getNodeOrdering($parent,$left){
        $ordering = $this->_orderArr[$parent][$left] + 1;
        return $ordering;
    }
    /**
     * Create breadcrumbs for nodes of tree
     * @param int ID of current node
     * @param int level of parent where you want get info
     * @return array An array store info of breadcrumbs
     *
     */
    public function breadcrumbs($id, $level_stop = null){
        $sql = 'SELECT parent.*
				FROM ' . $this->table . ' AS node,
			         ' . $this->table . ' AS parent
				WHERE node.lft BETWEEN parent.lft AND parent.rgt
			      AND node.id = ' . $id;

        if(isset($level_stop)){
            $sql .= ' AND parent.level > ' . $level_stop;
        }

        $sql .= ' ORDER BY node.lft';
        $arrData =  $this->getReadConnection()->query($sql);
        return $arrData->fetchAll();//getInternalResult() lay ra cau truy van
    }
    /**
     * Calculate total nodes
     * @param int ID of parent node
     *
     * @return int Total nodes
     */
    public function totalNode($parents = 0){
        $result = $this::findFirst(array("parent = $parents",'column'=>'lft,rgt'));
        $total = ($result->rgt - $result->lft + 1)/2;
        return $total;
    }
}